package mysql8学习.高级.第08章_索引的创建和设计原则;

/**
 *
 * 索引是一把双刃剑，可提高查询效率,但也会降低插入和更新的速度并占用磁盘空间。
 * 选择索弓的最终目的是为了使查询的速度变快，
 * 上面给出的原则是 最基本的准则，但不能拘泥于上面的准则，
 * 大家要在以后的学习和工作中进行不断的实践，根据应用的实际情况进行分析和判断，
 * 选择最合适的索引方式。
 *
 */
public class D_索引的设置原则之适合索引 {
}
/**
 * 哪些情况适合创建索引
 *
 * 1.字段的数值有唯一性的限制
 * 索引本身可以起到约束的作用，比如唯一索引主键索引都是可以起到唯一性约束的，
 * 因此在我们的数据表中,如果某个字段是唯一性的，就可以直接创建唯一性索引，或者主键索引。
 * 这样可以更快速地通过该索引来确定某条记录。
 * 例如，学生表中学号是具有唯一性的字段，为该字段建立唯-性索引可以很快确定某个学生的信息，
 * 如果使用姓名的话，可能存在同名现象,从而降低查询速度。
 * 业务上具有唯一特性的字段，即使是组合字段，也必须建成唯一索引。(来源: Alibaba)
 * 说明:不要以为唯一索引影响了 insert 速度，这个速度损耗可以忽略，但提高查找速度是明显的。
 *
 *
 * 2.频繁作为 WHERE 查询条件的字段
 * 某个字段在SELECT语句的WHERE条件中经常被使用到,那么就需要给这个字段创建索引了。
 * 尤其是在数据量大的情况下，创建普通索引就可以大幅提升数据查询的效率。
 *
 * 3.经常GROUP BY(分组)和ORDER BY（排序）的列
 * 索引就是让数据按照某种顺序进行存储或检索，
 * 因此当我们使用GROUP BY对数据进行分组查询，或者使用ORDER BY对数据进行排序的时候，
 * 就需要对分组或者排序的字段进行索引。如果待排序的列有多个，那么可以在这些列上建立组合索引。
 *   一般添加索引都是默认升序  可以在字段后面加 DESC 改成降序索引 8的新特性
 *   最左前缀原则
 *
 *
 * 4. UPDATE、DELETE 的WHERE条件列
 * 当我们对某条数据进行UPDATE或者DELETE操作的时候，是否也需要对WHERE的条件列创建索引呢?
 * 我们先看一下对数据进行UPDATE的情况:
 * 我们想要把name为462eed7ac6e791292a79对应的student_jid 修改为
 * 10002，当我们没有对name进行索引的时候，效率会远远低于有索引
 *
 * 对数据按照某个条件进行查询后再进行 UPDATE 或 DELETE 的操作,
 * 如果对 WHERE 字段创建了索引，就能大幅提升效率。
 * 原理是因为我们需要先根据 WHERE 条件列检索出来这条记录,然后再对它进行更新或删除。
 * 如果进行更新的时候，更新的字段是非索引字段,提升的效率会更明显，
 * 这是因为非索引字段更新不需要对索引进行维护
 *
 *
 * 5.DISTINCT （不同的）字段需要创建索引  去重
 * 有时候我们需要对某个字段进行去重，使用DISTINCT,那么对这个字段创建索引，也会提升查询效率。
 * 比如，我们想要查询课程表中不同的student_id 都有哪些，
 * 如果我们没有对student_id 创建索引  效率远低于创建索引
 * SELECT  DISTINCT(student_id) FROM 表名
 *
 * 6."多表"JOIN连接操作时，创建索引注意事项 类型必须一致
 * 首先，连接表的数量尽量不要超过3张，因为每增加一张表就相当于增加了一次嵌套的循环，
 * 数量级增长会非常快，严重影响查询的效率。
 * 其次，对WHERE条件创建索引，因为WHERE才是对数据条件的过滤。
 * 如果在数据量非常大的情况下，没有WHERE条件过滤是非常可怕的。
 *
 * 最后，对用于连接的字段创建索引，并且该字段在多张表中的类型必须一致。
 * 比如course_id在student_info 表和course表中都为it(11)类型，
 * 而不能一个为 int另一个为varchar类型。  否则索引失效
 *
 * 7.使用列的类型小的创建索引   每页大小16kb  类型小  相对更加扁平
 * 我们这里所说的类型大小指的就是该类型表示的数据范围的大小。
 * 我们在定义表结构的时候要显式的指定列的类型，以整数类型为例,有TINYINT、MEDIUMINT、 INT 、
 * BIGINT等，它们占用的存储空间依次递增，能表示的整数范围当然也是依次递增。
 * 如果我们想要对某个整数列建立索引的话，在表示的整数范围允许的情况下，
 * 尽量让索引列使用较小的类型,比如我们能使用INT就不要使用BIGINT，能使用MEDIUMINT就不要使用INT。
 * 这是因为:
 *   ●数据类型越小，在查询时进行的比较操作越快
 *   ●数据类型越小，索引占用的存储空间就越少,在一个数据页内就可以放下更多的记录，
 *      从而减少磁盘I/O带来的性能损耗，也就意味着可以把更多的数据页缓存在内存中，从而加快读写效率。
 *
 * 这个建议对于表的主键来说更加适用，因为不仅是聚簇索引中会存储主键值，
 * 其他所有的二级索弓|的节点处都会存储一份记录的主键值，
 * 如果主键使用更小的数据类型，也就意味着节省更多的存储空间和更高效的I/O。
 *
 *
 * 8.使用字符串前缀创建索引
 * 假设我们的字符串很长，那存储一个字符串就需要占用很大的存储空间。
 * 在我们需要为这个字符串列建立索引时，那就意味着在对应的B+树中有这么两个问题:
 * ●B+树索引中的记录需要把该列的完整字符串存储起来，更费时。
 *   而且字符串越长，在索 引中占用的存储空间越大。
 * ●如果B+树索引中索引列存储的字符串很长，那在做字符串比较时会占用更多的时间。
 * 我们可以通过截取字段的前面一部分内容建立索引，这个就叫前缀索引。
 * 这样在查找记录时虽然不能精确的定位到记录的位置，但是能定位到相应前缀所在的位置，
 * 然后根据前缀相同的记录的主键值回表查询完整的字符串值。
 * 既节约空间，又减少了字符串的比较时间，还大体能解决排序的问题。
 *
 * 例如，TEXT和BLOG类型的字段,进行全文检索会很浪费时间，如果只检索字段前面的若干字符,
 * 这样可以提高检索速度。
 * 在已经创建的表上添加索引
 * 方式一 ALTER（改变） TABLE 表名 ADD　INDEX/UNIQUE(唯一)
 *       自定义索引名（字段名(数字 表示前多少个字符做索引)）
 * 方式二 CREATE INDEX  UNIQUE(唯一性索引需添加)
 *       自定义索引名字 ON 表名(字段名(数字 表示前多少个字符做索引))
 *
 * SELECT COUNT(DISTINCT left(字段名.索引长度)) / count(*)  FROM 表名
 *   截取前多少个字符做选择度    看前多少个字符合适  太大了 浪费内存  太小了 没有对比
 *   一般20就高达90%
 *  [强制]在varchar字段上建立索引时，必须指定索引长度，没必要对全字段建立索引，
 *  根据实际文本区分度决定索引长度。
 *
 * 9.区分度高(散列性高)的列适合作为索引  比如根据性别做索引   就相当不明智了
 * 列的基数指的是某--列中不重 复数据的个数，
 * 比方说某个列包含值2，5，8， 2，5，8，2，5，8，虽然有9条记录,但该列的基数却是3。
 * 也就是说，在记录行数-定的情况下，列的基数越大，该列中的值越分散;
 * 列的基数越小，该列中的值越集中。
 * 这个列的基数指标非常重要，直接影响我们是否能有效的利用索引。
 * 最好为列的基数大的列建立索引，为基数太小列的建立索弓|效果可能不好。
 * 可以使用公式select count(distinct a)/count(*) from t1计算区分度,
 * 越接近1越好，-般超过33%就算是比较高效的索引了。
 * 拓展:联合索引把区分度高(散列性高)的列放在前面。
 *
 * 10.使用最频繁的列放到联合索引的左侧   最左前缀原则
 * 这样也可以较少的建立一些索引。同时，由于"最左前缀原则"，可以增加联合索引的使用率。
 *
 * 11.在多个字段都要创建索引的情况下，联合索引优于单值索引
 *
 */

